﻿using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Xrm.Sdk.Workflow.Fakes;
using Microsoft.Xrm.Sdk.Fakes;

namespace Xrm.Framework.Test.Unit.Fakes
{
    /// <summary>
    /// Base Class for all Dynamics CRM 2011 Custom Workflow Activities using Fakes
    /// </summary>
    public abstract class WFActivityUnitTest : Unit.WFActivityUnitTest
    {
        #region Instance Variables

        private readonly Guid _stubBusinessUnitId = Guid.NewGuid();
        private readonly Guid _stubContextUserId = Guid.NewGuid();
        private readonly Guid _stubCorrelationId = Guid.NewGuid();
        private readonly Guid _stubInitiatingUserId = Guid.NewGuid();
        private readonly DateTime _stubOperationCreatedOn = DateTime.Now;
        private readonly Guid _stubOperationId = Guid.NewGuid();
        private readonly Guid _stubOrganizationId = Guid.NewGuid();
        private readonly Guid _stubRequestId = Guid.NewGuid();

        #endregion

        #region Properties

        protected StubIWorkflowContext WorkflowContextStub { get; set; }

        protected StubIOrganizationService SystemOrganizationServiceStub { get; set; }

        protected StubIOrganizationService OrganizationServiceStub { get; set; }

        protected StubIOrganizationServiceFactory OrganizationServiceFactoryStub { get; set; }

        protected StubITracingService TracingServiceStub { get; set; }

        #endregion

        #region Constructors

        public WFActivityUnitTest()
        {
            Init();
        }

        #endregion

        #region Setup Stubs

        protected void Init()
        {
            SystemOrganizationServiceStub = new StubIOrganizationService();
            OrganizationServiceStub = new StubIOrganizationService();

            InitWorkflowContextMock(WorkflowContextStub);

            OrganizationServiceStub.CreateEntity = (entity) => Guid.NewGuid();

            SystemOrganizationServiceStub.CreateEntity = (entity) => Guid.NewGuid();

            OrganizationServiceFactoryStub.CreateOrganizationServiceNullableOfGuid = (id) =>
            {
                if (id == WorkflowContextStub.UserIdGet())
                    return OrganizationServiceStub;
                if (id == null)
                    return SystemOrganizationServiceStub;
                return new StubIOrganizationService();
            };
        }

        private void InitWorkflowContextMock(StubIWorkflowContext mock)
        {
            mock.BusinessUnitIdGet = () => _stubBusinessUnitId;
            mock.CorrelationIdGet = () => _stubCorrelationId;
            mock.DepthGet = () => 0;
            mock.InitiatingUserIdGet = () => _stubInitiatingUserId;
            mock.InputParametersGet = () => new ParameterCollection();
            mock.IsExecutingOfflineGet = () => false;
            mock.IsInTransactionGet = () => false;
            mock.IsOfflinePlaybackGet = () => false;
            mock.IsolationModeGet = () => (int) PluginAssembyIsolationMode.Sandbox;
            mock.MessageNameGet = () => string.Empty;
            mock.ModeGet = () => (int) PluginMode.Synchronous;
            mock.OperationCreatedOnGet = () => _stubOperationCreatedOn;
            mock.OperationIdGet = () => _stubOperationId;
            mock.OrganizationIdGet = () => _stubOrganizationId;
            mock.OrganizationNameGet = () => string.Empty;
            mock.OutputParametersGet = () => new ParameterCollection();
            mock.OwningExtensionGet = () => new EntityReference();
            mock.PostEntityImagesGet = () => new EntityImageCollection();
            mock.PreEntityImagesGet = () => new EntityImageCollection();
            mock.PrimaryEntityIdGet = Guid.NewGuid;
            mock.PrimaryEntityNameGet = () => string.Empty;
            mock.RequestIdGet = () => _stubRequestId;
            mock.SecondaryEntityNameGet = () => string.Empty;
            mock.SharedVariablesGet = () => new ParameterCollection();
            mock.UserIdGet = () => _stubContextUserId;
            mock.StageNameGet = () => string.Empty;
            mock.WorkflowCategoryGet = () => (int) WorkflowCategory.Workflow;
        }

        protected override IWorkflowContext CreateWorkflowContext() => WorkflowContextStub ?? (WorkflowContextStub = new StubIWorkflowContext());

        protected override ITracingService CreateTracingService() => TracingServiceStub ?? (TracingServiceStub = new StubITracingService());

        protected override IOrganizationServiceFactory CreateOrganizationServiceFactory() => OrganizationServiceFactoryStub ?? (OrganizationServiceFactoryStub = new StubIOrganizationServiceFactory());

        #endregion
    }
}